#ifndef __M_SINK_H__
#define __M_SINK_H__

#include"util.hpp"
#include<memory>
#include<mutex>
#include <fstream>
#include<sstream>
#include"format.hpp"
namespace log
{
    class LogSink
    {
        public:
        using ptr=std::shared_ptr<LogSink>;
        LogSink(){}
        virtual ~LogSink(){}
        virtual void log(const char* data,size_t len)=0;
    };
    //落地方向：标准输出
    class StdoutSink:public LogSink{
        public:
            void log(const char* data,size_t len)
            {
                std::cout.write(data,len);
            }
    };
    //落地方向：指定文件
    class FileSink:public LogSink
    {
        public: 
            FileSink(const std::string &pathname):_pathname(pathname)
            {
                util::File::createDirectory(util::File::path(pathname));
                _ofs.open(_pathname,std::ios::binary | std::ios::app);
                assert(_ofs.is_open());
            }
            void log(const char *data,size_t len)
            {
                _ofs.write(data,len);
                assert(_ofs.good());
            }

            private:
                std::string _pathname;
                std::ofstream _ofs; 
    };
    //落地方向：滚动文件，以文件大小滚动
    class RollRySizeSink: public LogSink
    {
        public: 
            RollRySizeSink(const std::string &basename,size_t max_size):
            _basename(basename),_max_fsize(max_size),_cur_fsize(0),_name_count(0)
            {
                std::string pathname=createNewFile();
                util::File::createDirectory(util::File::path(pathname));
                _ofs.open(pathname,std::ios::binary | std::ios::app);
                assert(_ofs.is_open());
            }
            void log(const char *data,size_t len)
            {
                if(_cur_fsize>=_max_fsize)
                {
                    _ofs.close();//关闭原来打开的文件
                    std::string pathname=createNewFile();
                    _ofs.open(pathname,std::ios::binary | std::ios::app);
                    assert(_ofs.is_open());
                    _cur_fsize=0;
                }
                _ofs.write(data,len);
                assert(_ofs.good());
                _cur_fsize+=len;
            }
        private:
            std::string createNewFile()
            { 
                //以时间来构造文件名
                time_t t=util::Date::now();
                struct tm lt;
                localtime_r(&t,&lt);
                std::stringstream filename;
                filename<<_basename;
                filename<<lt.tm_year+1900;
                filename<<lt.tm_mon+1;
                filename<<lt.tm_mday;
                filename<<lt.tm_hour;
                filename<<lt.tm_min;
                filename<<lt.tm_sec;
                filename<<"-";
                filename<<_name_count++;
                filename<<".log";
                return filename.str();
            }
        private:
            size_t _name_count;
            std::string _basename;
            std::ofstream _ofs;
            size_t _max_fsize;
            size_t _cur_fsize;
    };
    class SinkFactory
    {
        public:
            template<typename SinkType,typename ...Args>
            static LogSink::ptr create(Args &&...args)
            {
                return std::make_shared<SinkType>(std::forward<Args>(args)...);

            }
    };
}

#endif